<template>
  <div :class="animate" :style="{ height: height, width: width }" :id="chartOption.bindingDiv" ref="chartDiv"/>
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from '@/views/dashboard/mixins/resize'

import '../../animate/animate.css'

import {parseQueryString, fIsUrL} from '../../util/urlUtil'
import { linkChart} from "../../util/LinkageChart";
import { chartApiBar,remoteChartApi,chartBIanalysis } from '@/api/tool/datav/chartApi'
import VueEvent from '@/views/tool/datav/VueEvent'
import { addOption } from '../../codegen/codegen'
import { barPieBIanalysis } from '@/api/tool/datav/chartBI/chartBarPieBI'
import { getFormsource } from '@/api/tool/datav/formsource'
const animationDuration = 6000;
import { websocketCommand } from '../../util/websocket.js'

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "100%",
    },
    chartOption: {
      type: Object,
    },
    drawingList:{
      type: Array
    }
  },
  data() {
    return {
      chart: null,
      //dataOption: this.chartOption,
      timer: '',
      wsObj:null,
      wsFlag: false,
      wsTimer:'',
      wsValue:null,
      animate:this.className,
    };
  },
  watch: {
    width() {
      this.$nextTick(() => {
        this.chart.resize();
      });
    },
    height() {
      this.$nextTick(() => {
        this.chart.resize();
      });
    },
    chartOption: {
      deep: true,
      handler(newVal) {
        this.$nextTick(() => {
          this.setOptions(JSON.parse(JSON.stringify( newVal )));
        });
      }
    },
    'chartOption.theme': {
      handler() {
        if(this.chart != null) {
          this.chart.dispose();
          this.chart = null;
          this.initChart();
        }
      }
		},
    'chartOption.timeout': {
      handler() {
        this.chart.dispose();
        this.chart = null;
        this.initChart();
      }
    },
    'chartOption.dataSourceType': {
      handler(value) {
        //切换数据源重新连接
        if(value !== 'websocket') {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if(value !== 'url'){
          clearTimeout(this.timer);
        }
      }
    },
    'chartOption.interfaceKey': {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if(oldValue !== undefined && oldValue != '') {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    wsFlag: {
      handler(value) {
        if(!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value){
        this.animate = value;
      }
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
    clearTimeout(this.timer);
    if(this.wsFlag){
      this.closeWs()
    }
  },
  methods: {
    initChart() {
      echarts.registerTheme('customTheme', this.chartOption.theme);
      this.chart = echarts.init(this.$el, 'customTheme');
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if(this.timer != '') {
        clearTimeout(this.timer);
      }
      if((this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') && this.chartOption.timeout > 0) {

        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify( this.chartOption )));
          this.timer = setTimeout(() => {
            timerTask();
          }, this.chartOption.timeout);
        }

        timerTask();
      }else{
        this.setOptions(JSON.parse(JSON.stringify( this.chartOption )));
      }
    },
    setOptions: async function(dataOption) {
      //初始化数据
      //如果不是静态数据就调用接口给staticDataValue赋值
      if (dataOption.dataSourceType == 'url') {

        let paramJson = parseQueryString(dataOption.requestParameters);
        
        let interfaceURL = dataOption.interfaceURL;
        dataOption.staticDataValue = await chartApiBar(dataOption.requestMethod, interfaceURL, paramJson,dataOption.token);
        
      }else if (dataOption.dataSourceType == 'database') {
        if (dataOption.database.executeSql != undefined && dataOption.database.executeSql != '') {
          
          let result = [];
          if(dataOption.database.sqlType != 'custom'){
          
            result = await barPieBIanalysis(dataOption.database);
          }else{
            result = await chartBIanalysis(dataOption.database);
          }
          if (result.code == 200) {
            dataOption.staticDataValue = result.data;
            //console.log(dataOption.staticDataValue);
          } else {
            alert("操作数据库错误");
          }
        }
      }else if (dataOption.dataSourceType == 'form') {
        if (dataOption.formSource != undefined) {
          let response = await getFormsource(dataOption.formSource.id);
          dataOption.staticDataValue = JSON.parse(response.data.formData);
        }
      }else if (dataOption.dataSourceType == 'websocket') {
        if(dataOption.interfaceKey != undefined && dataOption.interfaceKey != '') {
          if(!this.wsFlag){
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs(); 
          }
          if(this.wsValue != null){
            dataOption.staticDataValue = this.wsValue;
          }
        }
      }
      
      if(dataOption.isRoseType == true){
        dataOption.series[1].roseType = true;
      }else{
        dataOption.series[1].roseType = false;
      }
      dataOption.series[0].name = dataOption.tooltipName;
      dataOption.series[1].name = dataOption.tooltipName;
      dataOption.series[1].radius[0] = dataOption.radiusI + '%';
      dataOption.series[1].radius[1] = dataOption.radiusO + '%';
      dataOption.series[1].center[0] = dataOption.centerX + '%';
      dataOption.series[1].center[1] = dataOption.centerY + '%';
      dataOption.legend.left = dataOption.legendcenterX + '%';
      dataOption.legend.top = dataOption.legendcenterY + '%';
      

      let xAxisData = [];
      let yAxisData = [];
      for( let value of dataOption.staticDataValue) {
        xAxisData.push(value.name);
        yAxisData.push(value.value); 
      };
      dataOption.xAxis.data     = xAxisData;
      dataOption.series[0].data = yAxisData;
      dataOption.series[1].data = dataOption.staticDataValue;
        
      let xAxisTemp, yAxisTemp;
      xAxisTemp = dataOption.xAxis;
      yAxisTemp = dataOption.yAxis;
      //是否竖显示
      if (dataOption.isVertical) {
          
        xAxisTemp = dataOption.yAxis;
        yAxisTemp = dataOption.xAxis;
      }
        
      //是否显示平均线
      if(dataOption.isMarkLine == true) {
        dataOption.series[0].markLine = {
            data: [
                  {type: 'average', name: '平均值'}
              ]
          }
      } else if (dataOption.isMarkLine == false || dataOption.isMarkLine == undefined) {
          dataOption.series[0].markLine = {}
      }

      //是否显示最大值和最小值
      if(dataOption.isMarkPoint == true) {
        dataOption.series[0].markPoint = {
            data: [
                {type: 'max', name: '最大值'},
                {type: 'min', name: '最小值'}
            ]
          }
      } else if (dataOption.isMarkPoint == false || dataOption.isMarkPoint == undefined) {
          dataOption.series[0].markPoint = {}
      }
      
      let option = {
          title: dataOption.title,
          tooltip: {//提示
              trigger: 'item',//饼图
              formatter: "{b} : {c}" + dataOption.unit,
          },
          legend: dataOption.legend,
          xAxis: xAxisTemp,
          yAxis: yAxisTemp,
          series: dataOption.series,
          //grid: {top: '55%'},
          grid: {
              top: 80,
              bottom: 30,
              left:150,
          },      
      };
      //执行通用处理函数
      if(dataOption.customData != undefined && dataOption.customData != ""){
        try {
          option = (
          
            //里面为要处理的代码块
          eval(dataOption.customData) 
          
          )(
            option,
            dataOption.staticDataValue,
            this.$refs.chartDiv
          );
        } catch (error) {
          console.log(error)
        }
       }

        //交互组件配置
      if(dataOption.interactData != undefined && dataOption.interactData != ""){
          try {
              option = (        
              //里面为要处理的代码块
              eval(dataOption.interactData)             
            )(
            option,
            dataOption.staticDataValue,
            this.$refs.chartDiv
            );
          } catch (error) {
            console.log(error)
          }               
       }

        this.chart.setOption(option, true);

        addOption(dataOption.bindingDiv, option);

        //开启图表联动
        if(dataOption.isLink == true){
          this.chart.off("click");
          this.chart.on('click', params => {
            //设置参数
            let arrObject = {             
              "legendName":params.name,
              "data":params.value
            }

            let arrs = JSON.stringify(arrObject);
            
            //获取绑定的图表
            let bindList = dataOption.bindList;
            
            if(bindList.length > 0){
              linkChart(dataOption.arrName, arrs, bindList,this.drawingList)
            }

          })
      }
      //开启图表下钻
      else if(dataOption.isDrillDown == true){
          this.chart.off("click");
          this.chart.on('click', params => {
            //设置参数
            let arrObject = {             
              "legendName":params.name,
              "data":params.value
            }

            let arrs = JSON.stringify(arrObject);
            
            //获取绑定的图表
            let drillDownChartOption = this.chartOption.drillDownChartOption;
                          
            if(drillDownChartOption != undefined && drillDownChartOption != null){
              
              this.$set(this.chartOption.drillDownChartOption.chartOption, 'requestParameters', "drillParam="+arrs);
              //发送下钻消息
              VueEvent.$emit("drill_down_msg", this.chartOption.drillDownChartOption);

            }
            
          })
      }
      else{
        //关闭图表联动，取消echart点击事件
        this.chart.off('click');
      }
      //开启远程图表控制
      if(dataOption.isRemote == true){
        if(dataOption.remote != undefined && dataOption.remote != null){
          this.chart.off("click");
          this.chart.on('click', params => {
            //设置参数
            let arrObject = {             
              "legendName":params.name,
              "data":params.value
            }

            let remoteData = { ...dataOption.remote };
            remoteData.query = arrObject;
            //调用接口
            remoteChartApi(remoteData)
            
          })
        }
      }
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg (e) {
      if(e.action == 'chat'){
        // console.log('服务端推送',e);
        this.wsValue = JSON.parse(e.result);
        this.setOptions(JSON.parse(JSON.stringify( this.chartOption )));
      }

    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs () {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(this.wsObj, 'create', 5000, this.chartOption.interfaceKey,this.sendHeartBeat, this.receiveMsg,this.reconnectWs,this.wsWarning);
    },
    // 断网重连，需要处理的逻辑
    reconnectWs(){      
      if(this.wsObj){
        console.log('%c websocket_reconnect','color:blue');
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat(){

      if(this.wsTimer != '') {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log('发送心跳',"ping");
        let obj = {action:"keep",key:this.chartOption.interfaceKey}
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      }
      wsTimerTask();
      
    },
    wsWarning(){
      //如果断开连接则显示组件警告动画并清除计数器
      if(this.wsObj.readyState == 3){
        this.animate = 'warning'
        clearTimeout(this.wsTimer);
      }
    },
    closeWs(){
      clearTimeout(this.wsTimer)
      websocketCommand(this.wsObj, 'close', 5000, this.chartOption.interfaceKey,this.sendHeartBeat, this.receiveMsg,this.reconnectWs,this.wsWarning);
    }
  }
};
</script>
